package com.chatgpt_backend.service.impl;

import com.chatgpt_backend.entity.account.Account;
import com.chatgpt_backend.entity.user.RegisterUser;
import com.chatgpt_backend.mapper.UserMapper;
import com.chatgpt_backend.service.AuthorizeService;
import com.chatgpt_backend.service.UserService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Optional;
import java.util.Random;
import java.util.concurrent.TimeUnit;


@Service
public class AuthorizeServiceImpl implements AuthorizeService {

    @Value("${spring.mail.username}")
    String from;

    @Resource
    UserMapper userMapper;

    @Resource
    UserService userService;

    @Resource
    MailSender mailSender;
    @Resource
    StringRedisTemplate stringRedisTemplate;

    BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (username == null)
            throw new UsernameNotFoundException("用户名不能为空");
        Account account =userMapper.getAccountByNameOrEmail(username);
        if (account == null)
            throw new UsernameNotFoundException("用户名或密码错误");
        System.out.println(userMapper.getRoleByAid(account.getId()));
        return User
                .withUsername(account.getUsername())
                .password(account.getPassword())
                .roles(userMapper.getRoleByAid(account.getId()))
                .build();
    }

    @Override
    public String sendValidEmail(String email, boolean hasAccount, String sessionId) {
        if (sessionId == null) return "拒绝访问";
        String key = sessionId + ":" + email + ":" + hasAccount;
        if (Boolean.TRUE.equals(stringRedisTemplate.hasKey(key))) {
            Long expire = Optional.ofNullable(stringRedisTemplate.getExpire(key, TimeUnit.SECONDS)).orElse(0L);
            if (expire > 120)
                return "请求频繁, 请稍后再试";
        }
        Integer aid = userMapper.isRegisterEmail(email);
        System.out.println(aid);
        if (hasAccount && aid == null)  return "此邮箱没有注册";
        if (!hasAccount && aid != null) return "此邮箱已被注册";
        Random random = new Random();
        int code = random.nextInt(900000) + 100000;
        SimpleMailMessage mailMessage = new SimpleMailMessage();

        try {
            mailMessage.setFrom("AI问答平台" + "<"+from+">");
            mailMessage.setTo(email);
            mailMessage.setSubject("您的验证邮件");
            mailMessage.setText("验证码: \n\t\t\t" + code + ", 有效期为3分钟");
            mailSender.send(mailMessage);
            stringRedisTemplate.opsForValue().set(key, String.valueOf(code), 3, TimeUnit.MINUTES);
            return null;
        }catch (MailException e) {
            return "邮件发送失败, 请检查邮件地址是否有效";
        }
    }

    @Override
    public String validateRegisterAccount(RegisterUser user, String sessionId) {
        if (sessionId == null) return "拒绝访问";
        String key = sessionId + ":" + user.getEmail() + ":false";
        if (Boolean.TRUE.equals(stringRedisTemplate.hasKey(key))) {
            String code = stringRedisTemplate.opsForValue().get(key);
            if (code == null) return "验证码失效, 请重新发送";
            if (code.equals(user.getCode())) {
                Integer aid = userMapper.isRegisterEmail(user.getEmail());
                if (aid != null) return "此邮箱已被注册";
                stringRedisTemplate.delete(key);
                String password = "{bcrypt}" + passwordEncoder.encode(user.getPassword());
                user.setPassword(password);
                if (userService.createAccount(user) > 0) return null;
                else return "服务器发生错误, 请联系管理员";
            }else return "验证码错误";
        }else return "请发送验证码到邮件";
    }

    @Override
    public String validateOnly(String email, String code, String sessionId) {
        String key = sessionId + ":" + email + ":true";
        if (Boolean.TRUE.equals(stringRedisTemplate.hasKey(key))) {
            String s = stringRedisTemplate.opsForValue().get(key);
            if (s==null) return "验证码已失效";
            if (s.equals(code)) {
                stringRedisTemplate.delete(key);
                return null;
            }else return "验证码错误";
        }else return "请发送验证码到邮箱";
    }

    @Override
    public Boolean resetPsd(String email, String newPassword) {
        newPassword = "{bcrypt}" + passwordEncoder.encode(newPassword);
        return userMapper.resetPsdByEmail(email, newPassword)>0;
    }
}
